// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using WriteState = System.Xml.WriteState;

namespace SnapObjects.Data
{
    internal class XNodeWriter : INodeWriter
    {
        private const string ROOTREFIX = "ArrayOf";

        private readonly XmlWriter _writer;
        private readonly StringBuilder _builder;

        public XNodeWriter()
        {
            _writer = XmlWriter.Create(_builder = new StringBuilder(),
                this.CreateXmlWriterSettings());
        }

        private XmlWriterSettings CreateXmlWriterSettings()
        {
            var xmlWriterSettings = new XmlWriterSettings
            {
                Indent = true,
                OmitXmlDeclaration = false
            };

            return xmlWriterSettings;
        }

        public INodeWriter WriteAsArray(string name)
        {
            if (_writer.WriteState == WriteState.Start)
            {
                _writer.WriteStartElement(ROOTREFIX + name);
            }
            else
            {
                _writer.WriteStartElement(name);
            }

            return this;
        }

        public INodeWriter WriteAsObject(string name)
        {
            _writer.WriteStartElement(name);

            return this;
        }

        public INodeWriter WriteAsValue(string name)
        {
            _writer.WriteStartElement(name);

            return this;
        }

        public void WriteEndArray()
        {
            _writer.WriteEndElement();
            _writer.Flush();
        }


        public void WriteEndObject()
        {
            _writer.WriteEndElement();
            _writer.Flush();
        }

        public void WriteNull()
        {
            this.WriteEndObject();
        }

        public void WriteRawValue(string raw)
        {
            var regex = new Regex(@"<\?xml.*\?>", RegexOptions.Compiled);

            raw = regex.Replace(raw, "");

            if (raw != null)
            {
                _writer.WriteRaw(raw);
            }

            this.WriteEndObject();
        }


        public void WriteValue(object value)
        {
            if (value != null)
            {
                if (value.GetType() == typeof(Guid))
                {
                    value = value.ToString();
                }
                else if (value.GetType().IsEnum)
                {
                    value = (int)value;
                }
                else if (value is DateTime dateTime)
                {
                    value = dateTime.ToString("yyyy-MM-dd HH:mm:ss.fffffff");
                }
                else if (value is TimeSpan ts)
                {
                    value = ts.ToString();
                }
                else if (value is DateTimeOffset dto)
                {
                    value = dto.ToString("yyyy-MM-ddThh:mm:sszzz");
                }

                _writer.WriteValue(value);
            }

            this.WriteEndObject();
        }

        public override string ToString()
        {
            return _builder.ToString();
        }
    }
}
